﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Microsoft.Lync.Controls;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace WorkItemCollaborator
{
    public delegate void SetWorkItemInternalDelegate(WorkItem workItem, Collection<User> projectUsers, string workItemEditorUrl);
    public class WicViewModel : INotifyPropertyChanged
    {
        readonly string[] excludedFields = new string[] { "Changed By", "Changed Date", "Revised Date", "Authorized As", "State Change Date" };
        public event PropertyChangedEventHandler PropertyChanged;

        public WicViewModel()
        {
            workItem = new CollaboratedWorkItem();
            workItemFields = new ObservableCollection<string>();
            settings = new WicSettings();
        }

        private CollaboratedWorkItem workItem;
        public CollaboratedWorkItem WorkItem
        {
            get { return workItem; }
            set
            {
                workItem = value;
                OnPropertyChanged("WorkItem");
            }
        }

        private ObservableCollection<string> workItemFields;
        public ObservableCollection<string> WorkItemFields
        {
            get { return workItemFields; }
            set
            {
                workItemFields = value;
                OnPropertyChanged("WorkItemFields");
            }
        }

        private WicSettings settings;
        public WicSettings Settings
        {
            get { return settings; }
            set
            {
                settings = value;
                OnPropertyChanged("Settings");
            }
        }

        protected void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        public void SetWorkItemInternal(WorkItem workItem, Collection<User> projectUsers, string workItemEditorUrl)
        {
            if (projectUsers != null && projectUsers.Count > 0)
            {
                WorkItem.IsUserLoading = false;
            }
            else
            {
                WorkItem.IsUserLoading = true;
            }

            RevisionCollection revisions = workItem.Revisions;

            if (WorkItemFields.Count == 0)
            {
                WorkItemFields.Clear();
                Collection<string> fields = GetWorkItemFields(workItem.Fields);
                foreach (var field in fields)
                {
                    WorkItemFields.Add(field);
                }
            }
            WorkItem.SelectedFieldIndex = 0;
            WorkItem.HistoryItems.Clear();
            List<Revision> revisionList = new List<Revision>();
            foreach (Revision tempRevision in revisions)
            {
                revisionList.Add(tempRevision);
            }
            string workItemType = workItem.Fields["Work Item Type"].Value as string;
            for (int i = (revisionList.Count - 1); i >= 0; i--)
            {
                Revision revision = revisionList[i];
                String history = (String)revision.Fields["History"].Value;
                if (!String.IsNullOrEmpty(history))
                {
                    history = RemoveHtmlTags(history);
                }
                DateTime changeDate = (DateTime)revision.Fields["Changed Date"].Value;
                string changedBy = (string)revision.Fields["Changed By"].Value;
                ConversationContextualInfo historyContextualInformation = new ConversationContextualInfo();

                historyContextualInformation.Subject = workItemType + " (" + workItem.Id + ") " + workItem.Title;
                historyContextualInformation.ContextualLink = workItemEditorUrl;
                User selectedUser = GetSelectedUser(projectUsers, changedBy);

                ObservableCollection<ChangedField> changedFields = null;
                if (i > 0)
                {
                    changedFields = GetChangedFields(workItem.Fields, revision, revisionList[i - 1]);
                }
                WorkItem.HistoryItems.Add(new HistoryItem(history, changeDate, selectedUser, historyContextualInformation, changedFields));
            }

            string assignedTo = (string)workItem.Fields["Assigned To"].Value;
            string createdBy = (string)workItem.Fields["Created By"].Value;
            ConversationContextualInfo workItemContextualInformation = new ConversationContextualInfo();
            workItemContextualInformation.Subject = workItemType + " (" + workItem.Id + ") " + workItem.Title;
            workItemContextualInformation.ContextualLink = workItemEditorUrl;
            WorkItem.Title = workItem.Title;
            WorkItem.WorkItemId = workItem.Id;
            User assignedToUser = GetSelectedUser(projectUsers, assignedTo);
            User createdByUser = GetSelectedUser(projectUsers, createdBy);
            WorkItem.AssignedTo = assignedToUser;
            WorkItem.CreatedBy = createdByUser;
            WorkItem.WorkItemContextualInformation = workItemContextualInformation;
            WorkItem.CurrentHistoryDisplayCount =
            WorkItem.HistoryItems.Count;
        }

        public void RefreshUsersOfCurrentlyDisplayedTaks(Collection<User> projectUsers)
        {
            if (WorkItem.HistoryItems != null && WorkItem.HistoryItems.Count > 0)
            {
                foreach (var historyItem in WorkItem.HistoryItems)
                {
                    if (historyItem.Owner != null)
                    {
                        historyItem.Owner = GetSelectedUser(projectUsers, historyItem.Owner.Name);
                    }
                }
            }
            WorkItem.AssignedTo = GetSelectedUser(projectUsers, WorkItem.AssignedTo.Name);
            WorkItem.CreatedBy = GetSelectedUser(projectUsers, WorkItem.CreatedBy.Name);
            WorkItem.IsUserLoading = false;
        }

        public void Clear()
        {
            WorkItem.HistoryItems.Clear();
            WorkItem.Title = string.Empty;
            WorkItem.WorkItemContextualInformation = null;
            WorkItem.WorkItemId = 0;
            WorkItem.AssignedTo = null;
            WorkItem.CreatedBy = null;
            WorkItem.Description = string.Empty;
        }

        private Collection<string> GetWorkItemFields(FieldCollection fieldCollection)
        {
            Collection<string> workItemFields = new Collection<string>();
            foreach (Field field in fieldCollection)
            {
                if (excludedFields.FirstOrDefault(row => row == field.Name) != null)
                    continue;
                workItemFields.Add(field.Name);
            }
            workItemFields = new Collection<string>(workItemFields.OrderBy(row => row.ToString()).ToList());
            workItemFields.Insert(0, "Any");
            return workItemFields;
        }

        private User GetSelectedUser(Collection<User> projectUsers, string userName)
        {
            User selectedUser = null;

            if (projectUsers != null)
            {
                selectedUser = projectUsers.FirstOrDefault(row => row.Name == userName);
            }

            if (selectedUser == null)
            {
                selectedUser = new User(userName, null);
            }
            return selectedUser;
        }

        private ObservableCollection<ChangedField> GetChangedFields(FieldCollection workItemFieldCollection, Revision current, Revision previous)
        {
            ObservableCollection<ChangedField> changedFields = new ObservableCollection<ChangedField>();
            foreach (Field field in workItemFieldCollection)
            {
                if (excludedFields.FirstOrDefault(row => row == field.Name) != null)
                    continue;
                bool isChanged = false;
                if (current.Fields[field.Name].Value != null && previous.Fields[field.Name].Value != null)
                {
                    isChanged = !current.Fields[field.Name].Value.Equals(previous.Fields[field.Name].Value);
                }
                else
                {
                    isChanged = current.Fields[field.Name].Value != previous.Fields[field.Name].Value;
                }

                if (isChanged)
                {
                    ChangedField changedField = new ChangedField()
                    {
                        FieldName = field.Name,
                        NewValue = current.Fields[field.Name].Value,
                        OldValue = previous.Fields[field.Name].Value
                    };
                    changedFields.Add(changedField);

                }
            }
            return changedFields;
        }

        private string RemoveHtmlTags(string html)
        {
            // Removes tags from passed HTML            
            var objRegEx = new System.Text.RegularExpressions.Regex("<[^>]*>");

            return objRegEx.Replace(html, "");
        }

    }
}
